package com.xcs.wx.repository.impl;

import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xcs.wx.constant.DataSourceType;
import com.xcs.wx.domain.Msg;
import com.xcs.wx.domain.vo.CountRecentMsgsVO;
import com.xcs.wx.domain.vo.MsgTypeDistributionVO;
import com.xcs.wx.domain.vo.TopContactsVO;
import com.xcs.wx.mapper.MsgMapper;
import com.xcs.wx.repository.MsgRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息 Repository 实现类
 *
 * @author xcs
 * @date 2023年12月25日 15时29分
 **/
@Slf4j
@Repository
@RequiredArgsConstructor
public class MsgRepositoryImpl extends ServiceImpl<MsgMapper, Msg> implements MsgRepository {

    /**
     * 查询指定发言人的消息，支持分页和排序。
     *
     * @param talker 消息发言人
     * @param nextSequence 下一个消息序列号，用于分页
     * @return 消息列表
     */
    @Override
    public List<Msg> queryMsgByTalker(String talker, Long nextSequence) {
        List<Msg> msgList = new ArrayList<>(); // 存储最终的消息列表
        List<String> msgDbList = DataSourceType.getMsgDb().stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); // 获取所有消息数据库，按顺序排序
        int offset = 20; // 每次查询的消息数量限制
        for (String poolName : msgDbList) { // 遍历所有数据库
            if (offset <= 0) break; // 如果已经查询足够数量的消息，则停止查询
            DynamicDataSourceContextHolder.push(poolName); // 切换到当前数据库
            List<Msg> queryResultList = super.list(Wrappers.<Msg>lambdaQuery()
                    .eq(Msg::getStrTalker, talker) // 查询条件：发言人匹配
                    .orderByDesc(Msg::getSequence) // 按序列号降序排序
                    .lt((nextSequence != null && nextSequence > 0), Msg::getSequence, nextSequence) // 如果提供了nextSequence，则查询序列号小于nextSequence的消息
                    .last("limit " + offset)); // 限制查询结果数量
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文
            offset -= queryResultList.size(); // 更新剩余需要查询的消息数量
            msgList.addAll(queryResultList); // 将查询结果添加到最终列表
        }
        return msgList; // 返回最终的消息列表
    }

    /**
     * 导出指定发言人的所有消息。
     *
     * @param talker 消息发言人
     * @return 消息列表
     */
    @Override
    public List<Msg> exportMsg(String talker) {
        List<Msg> msgList = new ArrayList<>(); // 存储最终的消息列表
        List<String> msgDbList = DataSourceType.getMsgDb(); // 获取所有消息数据库
        for (String poolName : msgDbList) { // 遍历所有数据库
            DynamicDataSourceContextHolder.push(poolName); // 切换到当前数据库
            List<Msg> queryResultList = super.list(Wrappers.<Msg>lambdaQuery()
                    .eq(Msg::getStrTalker, talker) // 查询条件：发言人匹配
                    .orderByDesc(Msg::getSequence)); // 按序列号降序排序
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文
            msgList.addAll(queryResultList); // 将查询结果添加到最终列表
        }
        return msgList; // 返回最终的消息列表
    }

    /**
     * 获取消息类型的分布统计。
     *
     * @return 消息类型分布视图列表
     */
    @Override
    public List<MsgTypeDistributionVO> msgTypeDistribution() {
        Optional<String> poolNameOptional = DataSourceType.getMsgDb().stream().max(Comparator.naturalOrder()); // 获取最大的消息数据库
        if (poolNameOptional.isPresent()) {
            DynamicDataSourceContextHolder.push(poolNameOptional.get()); // 切换到当前数据库
            List<MsgTypeDistributionVO> currentMsgsList = super.getBaseMapper().msgTypeDistribution(); // 调用mapper获取消息类型分布
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文
            return currentMsgsList; // 返回消息类型分布列表
        }
        return Collections.emptyList(); // 如果没有数据库，返回空列表
    }

    /**
     * 获取最近消息的统计。
     *
     * @return 最近消息统计视图列表
     */
    @Override
    public List<CountRecentMsgsVO> countRecentMsgs() {
        Optional<String> poolNameOptional = DataSourceType.getMsgDb().stream().max(Comparator.naturalOrder()); // 获取最大的消息数据库
        if (poolNameOptional.isPresent()) {
            DynamicDataSourceContextHolder.push(poolNameOptional.get()); // 切换到当前数据库
            List<CountRecentMsgsVO> currentMsgsList = super.getBaseMapper().countRecentMsgs(); // 调用mapper获取最近消息统计
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文
            return currentMsgsList.stream()
                    .sorted(Comparator.comparing(CountRecentMsgsVO::getType).reversed()) // 按类型降序排序
                    .collect(Collectors.toList()); // 返回排序后的列表
        }
        return Collections.emptyList(); // 如果没有数据库，返回空列表
    }

    /**
     * 获取最常联系的人统计。
     *
     * @return 最常联系的人视图列表
     */
    @Override
    public List<TopContactsVO> topContacts() {
        Optional<String> poolNameOptional = DataSourceType.getMsgDb().stream().max(Comparator.naturalOrder()); // 获取最大的消息数据库
        if (poolNameOptional.isPresent()) {
            DynamicDataSourceContextHolder.push(poolNameOptional.get()); // 切换到当前数据库
            List<TopContactsVO> currentContactsList = super.getBaseMapper().topContacts(); // 调用mapper获取最常联系的人统计
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文

            return currentContactsList.stream()
                    .sorted(Comparator.comparing(TopContactsVO::getTotal).reversed()) // 按总数降序排序
                    .limit(10) // 限制结果数量为10
                    .collect(Collectors.toList()); // 返回排序后的结果
        }
        return Collections.emptyList(); // 如果没有数据库，返回空列表
    }

    /**
     * 统计发送的消息数量。
     *
     * @return 发送的消息数量
     */
    @Override
    public int countSent() {
        Optional<String> poolNameOptional = DataSourceType.getMsgDb().stream().max(Comparator.naturalOrder()); // 获取最大的消息数据库
        if (poolNameOptional.isPresent()) {
            DynamicDataSourceContextHolder.push(poolNameOptional.get()); // 切换到当前数据库
            int count = getBaseMapper().countSent(); // 调用mapper统计发送的消息数量
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文
            return count; // 返回统计结果
        }
        return 0; // 如果没有数据库，返回0
    }

    /**
     * 统计接收的消息数量。
     *
     * @return 接收的消息数量
     */
    @Override
    public int countReceived() {
        Optional<String> poolNameOptional = DataSourceType.getMsgDb().stream().max(Comparator.naturalOrder()); // 获取最大的消息数据库
        if (poolNameOptional.isPresent()) {
            DynamicDataSourceContextHolder.push(poolNameOptional.get()); // 切换到当前数据库
            int count = getBaseMapper().countReceived(); // 调用mapper统计接收的消息数量
            DynamicDataSourceContextHolder.clear(); // 清除当前数据库上下文
            return count; // 返回统计结果
        }
        return 0; // 如果没有数据库，返回0
    }
}
